﻿using Models;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace GameUI
{
    public partial class GameWindow : Form
    {
        //constants
        private readonly Color CANVAS_DEFAULT_COLOR = Color.FromArgb(0, 0, 255);
        private readonly Rectangle Camera = new Rectangle(0, 0, 800, 600); //TODO: make seperate class!
        public enum State { READY, INITIALIZING, CLOSED };


        public GameWindow()
        {
            CurrentState = State.INITIALIZING;

            //autogen setup
            InitializeComponent();

            //other setup

            this.Location = new Point(600, 10);

            SetupCanvas();

            //handling of default events
            this.ResizeEnd += (sender, args) => { SetupCanvas(); };
            this.FormClosing += (sender, args) => 
            {
                string debug = "pre";
                CurrentState = State.CLOSED;
                debug = "post";
            };

            CurrentState = State.READY;
        }

        public State CurrentState { get; private set; }

        private void SetupCanvas()
        {
            //shortening "this.gameCanvas" to "canvas" :P
            PictureBox canvas = this.gameCanvas;

            Image img = new Bitmap(canvas.Width, canvas.Height);
            

            Graphics g = Graphics.FromImage(img);

            //fill the canvas with the default background color
            g.FillRectangle(new SolidBrush(CANVAS_DEFAULT_COLOR), new Rectangle(0,0, img.Width, img.Height));
            this.gameCanvas.Image = img;
        }



        public void SendCommand(string command)
        {
            //since this can be called from other than the creating thread
            //check for invoke requirement
            if (this.txtConsole.InvokeRequired)
            {
                Action<string> thisMethod = SendCommand;
                this.txtConsole.Invoke(thisMethod, command);    //<-- this line will call thisMethod from the creating thread..
            }
            else
            {
                string originalText = this.txtConsole.Text;
                string newText = originalText + "\r\n" + command;
                this.txtConsole.Text = newText;
            }
        }

        private void mySpawnEvent(GameObject entity)
        {
            SendCommand(String.Format("An entity has spawned at {0}", entity.Position));
        }

        public void Render(World world)
        {
            world.SpawnEvent -= mySpawnEvent;
            world.SpawnEvent += mySpawnEvent;

            
            Tile[,] grid = world.Grid;
            Random dice = new Random();
            Image img = new Bitmap(this.gameCanvas.Width, this.gameCanvas.Height);
            Graphics g = Graphics.FromImage(img);
            g.Clear(Color.Blue);

            //Color borderColour = Color.FromArgb(dice.Next(255), dice.Next(255), dice.Next(255));
            Color borderColour = Color.Black;
            
            try
            {
                Graphics realG = this.gameCanvas.CreateGraphics();
       
                for (int y = 0; y < world.TileY; y++)
                {
                    for (int x = 0; x < world.TileX; x++)
                    {
                        Tile tile = grid[x, y];
                        if (Camera.IntersectsWith(new Rectangle(tile.Position.ToPoint(), tile.Size)))
                        {
                            Rectangle border = new Rectangle(tile.Position.ToPoint().X, tile.Position.ToPoint().Y, tile.Size.Width, tile.Size.Height);

                            g.DrawImage(tile.Image, tile.Position.ToPoint());
                        }
                    }
                }
               

                //Entities
                foreach (GameObject gobj in world.Entities)
                {
                    g.DrawImage(gobj.Image, new Point((int)gobj.Position.X, (int)gobj.Position.Y));
                }

                realG.DrawImage(img, new Point(0, 0));
            }
            catch (ObjectDisposedException ex)
            {
                //TODO: handle disposed exception

            }
        }
    }
}
